/*
 * Copyright (C) 2022 KylinSoft Co., Ltd.
 *
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with
 * this program. If not, see <https://www.gnu.org/licenses/>.
 */

#include "tabletdesktopbackend.h"
#include "appnamesort.h"
#include <QString>
#include <KDesktopFile>
#include <KConfigGroup>
#include <QFileInfo>
#include <QLocale>
#include <QCoreApplication>
#include <QDBusConnection>
#include <QDebug>
#include <QDBusInterface>
#include <QDBusPendingCall>
#include <QDBusReply>
#include <QMetaEnum>
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <ukui/kappwidgetmanager.h>
#include "utils.h"
#include "desktopdataproviderprivate_p.h"
#include "database.h"

namespace UKUI {

DesktopDataProvider::DesktopDataProvider()
    : d_ptr(new DesktopDataProviderPrivate(this))
{
}
DesktopDataProvider::~DesktopDataProvider()
{
}

QMap<int, BaseItem *> DesktopDataProvider::getAllItems() const
{
    Q_D(const DesktopDataProvider);
    return d->dataHolder.allItems;
}

QMap<int, QList<int> > DesktopDataProvider::getAllItemIdsInPage() const
{
    Q_D(const DesktopDataProvider);
    return d->dataHolder.allItemIdsInHomeScreen;
}

QMap<int, QList<QList<int> > > DesktopDataProvider::getAllItemIdsInSet() const
{
    Q_D(const DesktopDataProvider);
    return d->dataHolder.itemIdsInSet;
}

QList<ItemId> DesktopDataProvider::getAppIdListAccordingCategory(BaseItem::Categories type)
{
    Q_D(DesktopDataProvider);
    QList<UKUI::ItemId> appIdList;
    QList<UKUI::ItemId> allItemId = d->dataHolder.allItems.keys();
    QList<BaseItem *> allItemInfo = d->dataHolder.allItems.values();
    for (int i = 0; i < d->dataHolder.allItems.size(); i++) {
        if (allItemInfo.at(i)) {
            QList<int> categories = allItemInfo.at(i)->getCategories();
            if (categories.contains(static_cast<int32_t>(type)))
                appIdList.append(allItemId.at(i));
        }
    }
    return d->sortAppIdAccordingLetter(appIdList);
}

QList<ItemId> DesktopDataProvider::getAllAppIdList()
{
    Q_D(DesktopDataProvider);
    QList<UKUI::ItemId> appIdList;
    QList<UKUI::ItemId> allItemId = d->dataHolder.allItems.keys();
    for (int i = 0; i < d->dataHolder.allItems.size(); i++) {
        if (d->dataHolder.allItems[allItemId[i]] && (d->dataHolder.allItems[allItemId[i]]->getType() == Type::Icon) )
            appIdList.append(allItemId[i]);
    }
    return d->sortAppIdAccordingLetter(appIdList);
}

void DesktopDataProvider::addHomeScreenPage()
{
    Q_D(DesktopDataProvider);
    int newPageIndex = d->dataHolder.allItemIdsInHomeScreen.count();
    d->dataHolder.allItemIdsInHomeScreen[newPageIndex] = QList<int>();
    d->database->addHomeScreenPage(newPageIndex, QList<int>());

    QList<QList<int> > itemIdsGrid;
    for (int row=0; row < d->desktopRow; ++row) {
        QList<int> columnItemIds;
        for (int col=0; col < d->desktopColumn; ++col) {
            columnItemIds.append(-1);
        }
        itemIdsGrid.append(columnItemIds);
    }
    d->dataHolder.itemIdsInPageGrid[newPageIndex] = itemIdsGrid;
}

void DesktopDataProvider::deleteHomeScreenPage()
{
    Q_D(DesktopDataProvider);
    if (!d->dataHolder.allItemIdsInHomeScreen.isEmpty()) {
        int page = d->dataHolder.allItemIdsInHomeScreen.count() - 1;
        d->database->deleteHomeScreenPage(page);
        d->dataHolder.allItemIdsInHomeScreen.remove(page);
    }
    if (!d->dataHolder.itemIdsInPageGrid.isEmpty()) {
        d->dataHolder.itemIdsInPageGrid.remove(d->dataHolder.itemIdsInPageGrid.count() - 1);
    }
    qDebug() << __func__ << d->dataHolder.allItemIdsInHomeScreen;
    qDebug() << __func__ << d->dataHolder.itemIdsInPageGrid;
}

void DesktopDataProvider::updateHomeScreenPageIds(int page, const QList<int> &ids)
{
    Q_D(DesktopDataProvider);
    Q_ASSERT(page >= 0);
    d->dataHolder.allItemIdsInHomeScreen[page] = ids;
    d->updateItemIdsInPageGridFromHomeScreenIds(page);
    d->database->updateHomeScreenPage(page, ids);
    qDebug() << __func__ << "backend" << page << ids;
}

void DesktopDataProvider::setSetName(int setId, const QString &name)
{
    Q_D(DesktopDataProvider);
    Q_ASSERT(d->dataHolder.itemIdsInSet.contains(setId) &&
             d->dataHolder.allItems.contains(setId));
    if (name.isEmpty()) {
        return;
    }
    d->dataHolder.allItems.value(setId)->setName(name);
    d->database->updateSetName(setId, name);
}

void DesktopDataProvider::createGroup(int groupId, const QString &groupName, const QList<int> &itemIds)
{
    Q_D(DesktopDataProvider);
    if (itemIds.count() != 2) {
        qWarning() << "Create group failed, the item number in group is not 2." << itemIds;
        return;
    }
    d->saveNewGroupData(groupId, groupName, itemIds);
    d->updateItemPositionAfterCreateGroup(itemIds.constFirst(), itemIds.constLast(), groupId);
}

void DesktopDataProvider::updateSet(int setId, const QList<QList<int> > &ids)
{
    Q_D(DesktopDataProvider);
    d->dataHolder.itemIdsInSet[setId] = ids;
    d->database->updateSetData(setId, ids);

    if (setId == d->kTaskbarGroupId) {
        d->writeTaskbarDataToTaskbarPanelConf(d->dataHolder.itemIdsInSet.value(d->kTaskbarGroupId).at(0));
    }
    qDebug() << __func__ << "backend" << setId << ids;
}

void DesktopDataProvider::removeGroup(int groupId)
{
    Q_D(DesktopDataProvider);
    d->dataHolder.itemIdsInSet.remove(groupId);
    d->database->deleteSet(groupId);
    qDebug() << __func__ << d->dataHolder.itemIdsInSet;
}

void DesktopDataProvider::uninsatllApp(const QString &desktopFile)
{
    Q_D(DesktopDataProvider);
    d->uninstaller.uninstallApp(desktopFile);
}

void DesktopDataProvider::replaceGroupIdWithAppId(int groupId, int appId)
{
    Q_D(DesktopDataProvider);
    bool exists;
    int itemIndex, setPageIndex;
    std::tie(exists, itemIndex, setPageIndex) = d->itemPositionInHomeScreen(groupId);
    if (exists) {
        d->dataHolder.allItemIdsInHomeScreen[setPageIndex][itemIndex] = appId;
        d->replaceIdInPageGrid(setPageIndex, groupId, appId);
        d->database->updateHomeScreenPage(setPageIndex, d->dataHolder.allItemIdsInHomeScreen.value(setPageIndex));
        qDebug() << __func__ << d->dataHolder.allItemIdsInHomeScreen.value(setPageIndex);
        qDebug() << __func__ << d->dataHolder.itemIdsInPageGrid.value(setPageIndex);
    }
}

void DesktopDataProvider::updateWidgetState(int state)
{
    AppWidget::KAppWidgetManager* appWidgetManager = new AppWidget::KAppWidgetManager(this);
    if (state == 2) {
        appWidgetManager->updateUserStatus("tablet-desktop", AppWidget::EDITABLE);
    } else {
        appWidgetManager->updateUserStatus("tablet-desktop", AppWidget::NORMAL);
    }
}

}
